using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Markup;
using System.Windows.Threading;
using System.ComponentModel;
using ViewOn.Kernel;
using ViewOn.Helper.WPF;
using ViewOn.UI.Control;
using Microsoft.Win32;
using ViewOnCore.HostContract;
using ViewOnCore.Helper.WPF;

namespace ViewOn.AddInsHostContract.UI
{

    sealed public class UIService : IUIService
    {

        #region Variables

        private GlowColors _glowColorsInstance = new GlowColors();

        ResourceDictionary _resource;

        private SolidColorBrush _color01 = new SolidColorBrush(Color.FromRgb(0, 0, 0));
        private SolidColorBrush _color02 = new SolidColorBrush(Color.FromRgb(0, 0, 0));
        private SolidColorBrush _color03 = new SolidColorBrush(Color.FromRgb(0, 0, 0));

        //----
        private string _applicationTitle = "";

        //---- Visual Packs
        private List<VisualPack> _visualPacksList = new List<VisualPack>();

        public event EventHandler ColorSchemeChanged;

        //---- Transitions
        private bool _isShaderSupported;
        private TransitionKindWithoutShader _transitionKindWithoutShader = TransitionKindWithoutShader.SmoothSliding;
        private TransitionKindWithShader _transitionKindWithShader = TransitionKindWithShader.LineReveal;

        #endregion

        #region Initialize

        public void Initialize(ResourceDictionary resource)
        {
            _isShaderSupported = RenderCapability.IsShaderEffectSoftwareRenderingSupported;

            //---- Load the visual packs
            Directory.CreateDirectory(System.Windows.Forms.Application.StartupPath + "/VisualPacks/");
            InitializeVisualPacks();

            //----
            _resource = resource;

            //Color baseColor = System.Windows.Media.Colors.Orange;
            Color baseColor = System.Windows.Media.Colors.Red;//Color.FromRgb(167, 181, 0);

            //---- Load default scheme from registry
            try
            {
                RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\VMS\\ViewOnTv\\ColorScheme");

                // The key doesn't exist; create it / open it
                if (key != null)
                {
                    int r = Int32.Parse((string)key.GetValue("R"));
                    int g = Int32.Parse((string)key.GetValue("G"));
                    int b = Int32.Parse((string)key.GetValue("B"));
                    baseColor = Color.FromRgb((byte)r, (byte)g, (byte)b);
                }
            }
            catch { }

            // Default color (Orange)
            SetBaseColor(baseColor);
        }

        #endregion

        #region Properties

        public string ApplicationTitle
        {
            get
            {
                return _applicationTitle;
            }
            set
            {
                _applicationTitle = value.Trim();

                Host.ApplicationWindow.Dispatcher.Invoke(DispatcherPriority.Send,
                      (DelegateInvoker)delegate { AsyncSetTitle(); });
            }
        }

        private void AsyncSetTitle()
        {
            if (_applicationTitle.Length < 1)
                Host.ApplicationWindow.Title = "ViewOn.tv";
            else
                Host.ApplicationWindow.Title = "ViewOn.tv - " + _applicationTitle;
        }

        public GlowColors GlowColors
        {
            get
            {
                return _glowColorsInstance;
            }
        }

        public SolidColorBrush Color01
        {
            get
            {
                return _color01;
            }
            set
            {
                _color01 = value;
            }
        }

        public SolidColorBrush Color02
        {
            get
            {
                return _color02;
            }
            set
            {
                _color02 = value;
            }
        }

        public SolidColorBrush Color03
        {
            get
            {
                return _color03;
            }
            set
            {
                _color03 = value;
            }
        }

        public bool IsShaderSupported
        {
            get
            {
                return _isShaderSupported;
            }
        }

        public TransitionKindWithShader TransitionKindWithShader
        {
            get
            {
                return _transitionKindWithShader;
            }
            set
            {
                _transitionKindWithShader = value;
            }
        }

        public TransitionKindWithoutShader TransitionKindWithoutShader
        {
            get
            {
                return _transitionKindWithoutShader;
            }
            set
            {
                _transitionKindWithoutShader = value;
            }
        }

        #endregion

        #region SetBaseColor

        public void SetBaseColor(Color baseColor)
        {
            HSL hsl = RGBHSL.RGB_to_HSL(baseColor);

            Color01 = new SolidColorBrush(RGBHSL.HSL_to_RGB(new HSL(hsl.H, hsl.S, Math.Max(0, hsl.L - 0.25))));
            Color02 = new SolidColorBrush(RGBHSL.HSL_to_RGB(new HSL(hsl.H, hsl.S, hsl.L)));
            Color03 = new SolidColorBrush(RGBHSL.HSL_to_RGB(new HSL(hsl.H, hsl.S, Math.Min(1, hsl.L + 0.25))));

            _resource["VOColor01"] = Color01;
            _resource["VOColor02"] = Color02;
            _resource["VOColor03"] = Color03;
            _resource["VOColor01Color"] = Color01.Color;
            _resource["VOColor02Color"] = Color02.Color;
            _resource["VOColor03Color"] = Color03.Color;

            //---- Save to registry
            try
            {
                RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\VMS\\ViewOnTv\\ColorScheme", true);

                // The key doesn't exist; create it / open it
                if (key == null)
                    key = Registry.CurrentUser.CreateSubKey("Software\\VMS\\ViewOnTv\\ColorScheme");

                key.SetValue("R", baseColor.R);
                key.SetValue("G", baseColor.G);
                key.SetValue("B", baseColor.B);
            }
            catch (Exception e)
            {
            }
        }

        #endregion

        #region SetBackgroundXAML

        public void SetBackgroundXAML(string backgroundXAML)
        {
            string xaml = "";

            xaml += "<Grid";
            xaml += " xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"";
            xaml += " xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">";

            // Preprocessing
            string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
            backgroundXAML = backgroundXAML.Replace("{x:static VisualPacks.RootFolder}", baseDirectory + "VisualPacks");

            if (backgroundXAML != null)
                xaml += backgroundXAML;

            xaml += "</Grid>";

            StringReader stringReader = new StringReader(xaml);
            XmlReader xmlReader = XmlTextReader.Create(stringReader, new XmlReaderSettings());
            UIElement background = (UIElement)XamlReader.Load(xmlReader);

            SkinWindow.MainWindow.SetBackgroundXAML(background);
        }

        #endregion

        #region SetColorScheme

        public void SetColorScheme(Color color10,
                                        Color color11,
                                        Color color12,
                                        Color color13,
                                        Color color14,
                                        Color color15,
                                        Color color16,
                                        Color color17,
                                        Color color18,
                                        Color color19,
                                        Color color1A)
        {
            Application.Current.Resources.Remove("VOColor10");
            Application.Current.Resources.Add("VOColor10", new SolidColorBrush(color10));
            Application.Current.Resources.Remove("VOColor11");
            Application.Current.Resources.Add("VOColor11", new SolidColorBrush(color11));
            Application.Current.Resources.Remove("VOColor12");
            Application.Current.Resources.Add("VOColor12", new SolidColorBrush(color12));
            Application.Current.Resources.Remove("VOColor13");
            Application.Current.Resources.Add("VOColor13", new SolidColorBrush(color13));
            Application.Current.Resources.Remove("VOColor14");
            Application.Current.Resources.Add("VOColor14", new SolidColorBrush(color14));
            Application.Current.Resources.Remove("VOColor15");
            Application.Current.Resources.Add("VOColor15", new SolidColorBrush(color15));
            Application.Current.Resources.Remove("VOColor16");
            Application.Current.Resources.Add("VOColor16", new SolidColorBrush(color16));
            Application.Current.Resources.Remove("VOColor17");
            Application.Current.Resources.Add("VOColor17", new SolidColorBrush(color17));
            Application.Current.Resources.Remove("VOColor18");
            Application.Current.Resources.Add("VOColor18", new SolidColorBrush(color18));
            Application.Current.Resources.Remove("VOColor19");
            Application.Current.Resources.Add("VOColor19", new SolidColorBrush(color19));
            Application.Current.Resources.Remove("VOColor1A");
            Application.Current.Resources.Add("VOColor1A", new SolidColorBrush(color1A));

            //---- Update the glows
            GlowColors.VOGColor10 = color10;
            GlowColors.VOGColor1A = color1A;
        }

        #endregion

        #region Initialize / Load / Save Visual packs

        private void InitializeVisualPacks()
        {
            string basePath = System.Windows.Forms.Application.StartupPath + "/VisualPacks/";
            string[] visualPacksPaths = Directory.GetFiles(basePath);
            foreach (string path in visualPacksPaths)
            {
                if (!path.EndsWith(".vvp"))
                    continue;

                string name = new FileInfo(path).Name;
                name = name.Substring(0, name.Length - 4);

                VisualPack pack = LoadVisualPack(name);
                if (pack != null)
                    _visualPacksList.Add(pack);
            }

            // Try to load the current visual pack
            if (FindVisualPack(CurrentVisualPackName) == null)
                CurrentVisualPackName = "Darker"; // reset
        }

        public VisualPack LoadVisualPack(string name)
        {
            string path = System.Windows.Forms.Application.StartupPath + "/VisualPacks/" + name + ".vvp";

            XmlDocument XmlDatabase = new XmlDocument();
            try
            {
                XmlDatabase.Load(path);

                VisualPack pack = new VisualPack();

                XmlElement node = XmlDatabase.SelectSingleNode("/visualpack") as XmlElement;
                pack.Name = XmlConvert.DecodeName(node.Attributes["Name"].Value);
                pack.Mode = (VisualPackMode)Enum.Parse(typeof(VisualPackMode), XmlConvert.DecodeName(node.Attributes["Mode"].Value));
                pack.Animation = XmlConvert.DecodeName(node.Attributes["Animation"].Value);
                pack.ImagePath = XmlConvert.DecodeName(node.Attributes["ImagePath"].Value);
                pack.XAML = XmlConvert.DecodeName(node.Attributes["XAML"].Value);

                try
                {
                    pack.Color10 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color10"].Value));
                    pack.Color11 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color11"].Value));
                    pack.Color12 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color12"].Value));
                    pack.Color13 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color13"].Value));
                    pack.Color14 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color14"].Value));
                    pack.Color15 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color15"].Value));
                    pack.Color16 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color16"].Value));
                    pack.Color17 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color17"].Value));
                    pack.Color18 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color18"].Value));
                    pack.Color19 = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color19"].Value));
                    pack.Color1A = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["Color1A"].Value));
                    pack.ColorText = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["ColorText"].Value));
                    pack.ColorIcon = (Color)ColorConverter.ConvertFromString(XmlConvert.DecodeName(node.Attributes["ColorIcon"].Value));

                    if (node.HasAttribute("Gradient01"))
                        pack.Gradient01 = (LinearGradientBrush)XamlReader.Load(XmlReader.Create(new StringReader(XmlConvert.DecodeName(node.Attributes["Gradient01"].Value))));
                    if (node.HasAttribute("Gradient02"))
                        pack.Gradient02 = (LinearGradientBrush)XamlReader.Load(XmlReader.Create(new StringReader(XmlConvert.DecodeName(node.Attributes["Gradient02"].Value))));
                }
                catch { }

                if (name == "Darker")
                    pack.CanModify = false;
                if (name == "Black")
                    pack.CanModify = false;
                if (name == "Lighter")
                    pack.CanModify = false;
                if (name == "Default")
                    pack.CanModify = false;

                return pack;
            }
            catch
            {

            }

            return null;
        }

        public void SaveVisualPack(VisualPack visualPack)
        {
            string path = System.Windows.Forms.Application.StartupPath + "/VisualPacks/" + visualPack.Name + ".vvp";

            //----
            XmlDocument XmlDatabase = new XmlDocument();

            XmlDatabase.LoadXml("<visualpack></visualpack>");
            XmlNode node = XmlDatabase.SelectSingleNode("/visualpack");

            XmlAttribute attribute = XmlDatabase.CreateAttribute("Name");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Name);
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Mode");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Mode.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Animation");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Animation);
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("ImagePath");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.ImagePath);
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color10");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color10.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color11");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color11.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color12");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color12.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color13");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color13.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color14");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color14.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color15");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color15.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color16");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color16.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color17");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color17.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color18");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color18.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color19");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color19.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Color1A");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.Color1A.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("ColorText");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.ColorText.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("ColorIcon");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.ColorIcon.ToString());
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("XAML");
            attribute.Value = XmlConvert.EncodeLocalName(visualPack.XAML);
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Gradient01");
            attribute.Value = XmlConvert.EncodeLocalName(XamlWriter.Save(visualPack.Gradient01));
            node.Attributes.Append(attribute);

            attribute = XmlDatabase.CreateAttribute("Gradient02");
            attribute.Value = XmlConvert.EncodeLocalName(XamlWriter.Save(visualPack.Gradient02));
            node.Attributes.Append(attribute);

            XmlDatabase.Save(path);
        }

        #endregion

        #region Visual Pack

        public string CurrentVisualPackName
        {
            get
            {
                return Host.SettingsService.CurrentVisualPackName;
            }
            set
            {
                Host.SettingsService.CurrentVisualPackName = value;
            }
        }

        public VisualPack NewVisualPack()
        {
            VisualPack pack = new VisualPack();
            _visualPacksList.Add(pack);
            return pack;
        }

        public List<VisualPack> VisualPacks
        {
            get
            {
                return _visualPacksList;
            }
        }

        public VisualPack FindVisualPack(string name)
        {
            name = name.Trim();
            foreach (VisualPack pack in _visualPacksList)
                if (pack.Name.Trim() == name)
                    return pack;

            return null;
        }

        #endregion

        #region ApplyVisualPack

        public string ApplyVisualPack(VisualPack visualPack)
        {
            try
            {
                //---- Set new one as current
                CurrentVisualPackName = visualPack.Name;

                //---- Apply changes
                SetColorScheme(visualPack.Color10,
                                visualPack.Color11,
                                visualPack.Color12,
                                visualPack.Color13,
                                visualPack.Color14,
                                visualPack.Color15,
                                visualPack.Color16,
                                visualPack.Color17,
                                visualPack.Color18,
                                visualPack.Color19,
                                visualPack.Color1A);

                //---- Text & icon colors
                Application.Current.Resources.Remove("VOColorText");
                Application.Current.Resources.Add("VOColorText", new SolidColorBrush(visualPack.ColorText));

                Application.Current.Resources.Remove("VOColorIcon");
                Application.Current.Resources.Add("VOColorIcon", new SolidColorBrush(visualPack.ColorIcon));

                //---- Set background
                Host.UIService.SetBackgroundXAML(visualPack.XAML);

                //----
                Application.Current.Resources.Remove("VOGradient01");
                Application.Current.Resources.Add("VOGradient01", visualPack.Gradient01);

                Application.Current.Resources.Remove("VOGradient02");
                Application.Current.Resources.Add("VOGradient02", visualPack.Gradient02);
            }
            catch (Exception e)
            {
                return e.Message;
            }

            if (ColorSchemeChanged != null)
                ColorSchemeChanged(null, null);

            return null;
        }

        #endregion

        #region DeleteVisualPack

        public void DeleteVisualPack(string packName)
        {
            _visualPacksList.Remove(FindVisualPack(packName));

            try
            {
                string path = System.Windows.Forms.Application.StartupPath + "/VisualPacks/" + packName + ".vvp";

                File.Delete(path);
            }
            catch { }
        }

        #endregion

    }

}
